﻿//基于epoll模型的文件服务器开发
#include <cstdio>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "wrap.h"
#include "http_com.h"


int main()
{
    int lfd;
    int cfd;
    int flag;
    int nready;
    int i;
    int n;
    int ret;
    int opt = 1;
    int epfd;
    socklen_t len;
    struct epoll_event event, ev[1024];
    //创建一颗epoll树
    epfd = epoll_create(1);
    if (epfd < 0) {
        perror("epoll_create error\n");
        close(cfd);
        exit(-1);
    }
    struct sockaddr_in serv, client;
    serv.sin_family = AF_INET;
    serv.sin_port = htons(8888);
    inet_pton(AF_INET, "192.168.211.128", &serv.sin_addr.s_addr);
    lfd = Socket(AF_INET, SOCK_STREAM, 0);
    Setsockopt(lfd, &opt);
    Bind(lfd, &serv, sizeof(serv));
    //上树
    event.data.fd = lfd;
    event.events = EPOLLIN;
    ret = epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &event);
    Listen(lfd, 128);
    int sockfd;
    for (i = 0; i < 1024; i++) {
        ev[i].data.fd = -1;
    }

    while (1) {
        nready = epoll_wait(epfd, ev, 1024, -1);
        if (nready < 0) {
            perror("epoll_wait error\n");
            epoll_ctl(epfd, EPOLL_CTL_DEL, lfd, NULL);
            close(lfd);
            exit(-1);
        }
        char sIP[16] = "\0";
        for (i = 0; i < nready; i++) {
            //新的连接到来
            if ((ev[i].data.fd == lfd) && (ev[i].events & EPOLLIN)) {
                //接受新的连接
                cfd = Accept(lfd, &client, &len);
      
                if (ntohs(client.sin_port) == 0) {
                    close(cfd);
                    continue;
                }
                //设置文件描述符为非阻塞
                flag = fcntl(cfd, F_GETFD, 0);
                flag |= O_NONBLOCK;
                fcntl(cfd, F_SETFD, flag);
                //上树
                event.data.fd = cfd;
                event.events = EPOLLIN;
                ret = epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &event);
                if (ret != 0) {
                    perror("epoll_ctl error\n");
                    close(cfd);
                    epoll_ctl(epfd, EPOLL_CTL_DEL, lfd, NULL);
                    close(lfd);
                    exit(-1);
                }
                memset(sIP, 0x00, sizeof(sIP));
                printf("receive now link\n");
                printf("client:port-->[%d],ip-->[%s]\n", ntohs(client.sin_port), inet_ntop(AF_INET, &client.sin_addr.s_addr, sIP, sizeof(sIP)));
                continue;
            }
            //进行通信，接受http请求
            sockfd = ev[i].data.fd;
            ret = http_request(sockfd);
            if (ret != 0) {
                //错误
                epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);
                close(sockfd);
                printf("http_request error\n");
                continue;
            }
        }
    }
    return 0;
}

//int main() {
//	int fd = open("./test.txt", O_CREAT | O_RDWR | O_APPEND, 0755);
//	if (fd < 0) {
//		perror("open error\n");
//		return -1;
//	}
//	int n = write(fd, "helloworld\nnihaoshijie\nni", sizeof("helloworld\nnihaoshijie\nni"));
//	if (n <= 0) {
//		perror("write error\n");
//		return -1;
//	}
//	char buf[64] = "\0";
//	n = readline(fd, buf, sizeof(buf));
//	printf("n=[%d],buf=[%s]\n",n,buf);
//	sleep(20);
//
//	return 0;
//}

